package org.usmile.algorithms.learn.heap;

import java.util.Arrays;

public class Heapify {
    public static void heapify(int[] nums) {
        if (nums == null || nums.length <= 1) {
            return;
        }
        int lastLeafIndex = nums.length - 1;

        int lastNonLeafIndex = (lastLeafIndex - 1) / 2;

        for (int i = lastNonLeafIndex; i >= 0; i--) {
            shiftDown(nums, i);
        }
    }

    public static void sort(int[] nums) {
        heapify(nums);
        int round = nums.length - 1;
        for (int i = 0; i <= round; i++) {
            int temp = nums[0];
            nums[0] = nums[round - i];
            nums[round - i] = temp;
            sortShiftDown(nums, i + 1);
        }
    }

    private static void sortShiftDown(int[] nums, int sorted) {
        int index = 0;
        int num = nums[0];
        while (2 * index + 1 < nums.length - sorted) {
            int maxChildIndex = 2 * index + 1;
            if (2 * index + 2 < nums.length - sorted) {
                if (nums[2 * index + 2] > nums[2 * index + 1]) {
                    maxChildIndex = 2 * index + 2;
                }
            }

            if (num > nums[maxChildIndex]) {
                break;
            }

            nums[index] = nums[maxChildIndex];
            index = maxChildIndex;
        }

        nums[index] = num;
    }

    private static void shiftDown(int[] nums, int index) {
        int num = nums[index];
        while (2 * index + 1 < nums.length) {
            int maxChildIndex = 2 * index + 1;
            if (2 * index + 2 < nums.length) {
                if (nums[2 * index + 2] > nums[2 * index + 1]) {
                    maxChildIndex = 2 * index + 2;
                }
            }

            if (num > nums[maxChildIndex]) {
                break;
            }

            nums[index] = nums[maxChildIndex];
            index = maxChildIndex;
        }

        nums[index] = num;
    }

    public static void main(String[] args) {
        int[] nums = new int[]{15, 17, 19, 13, 22, 16, 28, 30, 42, 66};
        Heapify.sort(nums);

        System.out.println(Arrays.toString(nums));
    }
}
